package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sun.xml.bind.v2.TODO;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private Client client;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void syncProductList() {
        // 1、从IOT平台查询产品列表
        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(1);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setPageSize(10);
        List<ProductVo> productVoList = new ArrayList<>();

        try {
            QueryProductListResponse response = client.queryProductList(request);


            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfoList = response.getBody().getData().getList().getProductInfo();
            productInfoList.forEach(productInfo -> {

                ProductVo productVo = new ProductVo();
                productVo.setProductKey(productInfo.getProductKey());
                productVo.setProductName(productInfo.getProductName());
                productVoList.add(productVo);

            });
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        // 2、保存到Redis中

        redisTemplate.boundValueOps(CacheConstants.ALL_PRODUCT_KEY).set(JSONUtil.toJsonStr(productVoList));

    }

    @Override
    public List<ProductVo> allProduct() {
        String jsonStr = redisTemplate.boundValueOps(CacheConstants.ALL_PRODUCT_KEY).get();
        List<ProductVo> productVoList = JSONUtil.toList(jsonStr, ProductVo.class);

        return productVoList;
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        // 1、根据设备名称查询是否存在，如果存在 结束 抛异常
        Integer count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        // 2、IOT平台新增设备
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse deviceResponse = null;
        try {
            // 新增设备
            deviceResponse = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        // 继续判断
        if (deviceResponse.getBody()==null||deviceResponse.getBody().getSuccess()==false) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        // 向阿里云的IOT平台新增设备后返回的设备id
        String iotId = deviceResponse.getBody().getData().getIotId();

        // 3、准备需要保存到表中的数据
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(iotId);
        //   3.1  从IOT中查询产品，获取产品的名称
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            e.printStackTrace();
            // TODO 删除第2步新增的数据
            deleteDevice(iotId);
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);

        }
        if (queryProductResponse.getBody()==null||queryProductResponse.getBody().getSuccess()==false) {
            // TODO 删除第2步新增的数据
            deleteDevice(iotId);
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        device.setProductName(queryProductResponse.getBody().getData().getProductName());
        //  3.2判断位置类型
        if (deviceDto.getLocationType()== DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal()) {
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        // 4、保存到数据库
        try {
            deviceMapper.insertSelective(device);
        } catch (Exception e) {
            e.printStackTrace();
            //   4.1如果抛异常，删除第2步新增的设备数据
            deleteDevice(iotId);
        }

    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        Page<DeviceVo> deviceVoPage = ( Page<DeviceVo>)deviceMapper.findList(dto.getDeviceName(),dto.getLocationType(),dto.getProductKey());
        return PageResponse.of(deviceVoPage, DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) {
        // 先从IOT查询
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse detailResponse = null;
        try {
            detailResponse = client.queryDeviceDetail(request);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_SERVICE_DATA_ERROR);
        }
        // 判断是否获取到数据
        if(detailResponse==null||detailResponse.getBody().getSuccess()==false){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_SERVICE_DATA_ERROR);
        }
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData deviceDetailData = detailResponse.getBody().getData();

        // 把deviceDetailData属性赋值到deviceVo
        DeviceVo deviceVo = BeanUtil.toBean(deviceDetailData, DeviceVo.class);

        // 根据IOTId查询mysql中的设备
        DeviceVo deviceVoFromDb = deviceMapper.selectByIotId(request.getIotId());

        // 开始合并两个VO  拷贝属性时忽略null值
        BeanUtil.copyProperties(deviceVoFromDb,deviceVo, CopyOptions.create().ignoreNullValue());


        return deviceVo;
    }

    @Override
    public QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            QueryThingModelPublishedResponse response = client.queryThingModelPublished(request);
            return response.getBody().getData();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
    }

    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            QueryDevicePropertyStatusResponse response = client.queryDevicePropertyStatus(request);
            return response.getBody().getData();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
    }

    private void deleteDevice(String iotId) { //设备id
        DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
        deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        deleteDeviceRequest.setIotId(iotId);
        try {
            client.deleteDevice(deleteDeviceRequest);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
    }

}